package codeoffloading;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;

import netcom.messages.ExecutionReplyMessage;
import netcom.messages.ExecutionRequestMessage;

public class ExecutionThread implements Runnable {

	private ExecutionRequestMessage reqM;
	private Socket senderSocket;
	private static int messageId = 0;
	private boolean threadIsFinished = true;

	public ExecutionThread(Socket sock, ExecutionRequestMessage m) {
		reqM = m;
		senderSocket = sock;
	}

	public void run() {
		if (messageId == Integer.MAX_VALUE) messageId = 0;
		messageId++;
		int mmid = messageId;
		
		threadIsFinished = false;
		Object o = this.localExecuteMethodOnClass(reqM.getExecutionMethod(),
				reqM.getParamas(), reqM.getExecutableClass());
		boolean ret = o != null;

		ExecutionReplyMessage m = new ExecutionReplyMessage(mmid,
				reqM.getMessageId(), reqM.getExecutableClass(),
				reqM.getExecutionMethod(), o, ret);
		OutputStream out;
		try {
			out = senderSocket.getOutputStream();

			byte[] b = utilities.SerializableClassUtility.getBytesFromClass(m);
			DataOutputStream dos = new DataOutputStream(out);
			int len = b.length;
			dos.writeInt(len);
			if (len > 0) {
				dos.write(b, 0, len);
			}

			dos.close();
			senderSocket.close();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		threadIsFinished = true;

	}

	private Object localExecuteMethodOnClass(String methodName, Object[] prm,
			ExecutableClass exCla) {
		Method toExec = null;
		for (Method m : exCla.getClass().getMethods()) {
			System.out.println(m.getName() + " " + methodName);
			if (m.getName().compareTo(methodName) == 0) {
				toExec = m;
				break;
			}
		}
		
		if(toExec == null) return null;
		
		try {
			// single paramater method
			if (prm.length < 2)
				return toExec.invoke(exCla, prm[0]);
			else
				return toExec.invoke(exCla, prm);
		} catch (IllegalArgumentException e) {
			e.printStackTrace(); return null;
		} catch (IllegalAccessException e) {
			e.printStackTrace(); return null;
		} catch (InvocationTargetException e) {
			e.printStackTrace(); return null;
		}

	}

	public boolean hasFinished() {
		return threadIsFinished;
	}

}
